• 问题

    当类实现接口时,接口就充当可以引用这个类的实例类型。因此,类实现了接口,就表明客户端对这个类的实例可以实施某些动作为了任何其他目的而定义的接口是不恰当的。那么,在实际开发中存在哪些定义接口不恰当的方式?

  • 解决

    使用接口一种典型的错误方式就是:常量接口。常量接口(constant interface):这种接口不包含任何方法,它只包含静态的final域,每个域都导出一个常量。

    常量接口是对接口的一种不良使用,主要有这样两个原因:

    1. 类在内部使用某些常量,纯粹是实现细节,实现常量接口,会导致把这样的实现细节泄露到该类的导出API中,因为接口中所有的域都是及方法public的。
    2. 类实现常量接口,这对于这个类的用户来讲并没有实际的价值。实际上,这样做返回会让他们感到更糊涂,这还代表了一种承诺:如果在将来的发行版本中,这个类被修改了,它不再需要使用这些常量了,依然必须实现这个接口,以确保二进制兼容性。如果非final类实现了常量接口,它的所有子类的命名空间都受到了污染。Java平台类库中存在几个常量å接口,如java.io.ObjectStreamConstants,这些接口都是反面典型,不值得效仿。

    那既然不适合存在全部都是导出常量的常量接口,那么如果需要导出常量,它们应该放在哪里呢?

    1. 如果这些常量与某些现有的类或者接口紧密相关,就应该把这些常量添加到这个类或者接口中,注意,这里说添加到接口中并不是指的常量接口。

    2. 在Java平台类库中所有的数值包装类都导出MIN_VALUEMAX_VALUE常量。如果这些常量最好被看作是枚举类型成员,那就应该用枚举类型来导出。

    3. 使用不可实例化的工具类来导出这些常量,例如:

      public class PhysicalConstants {
          private PhysicalConstants() {}
          public static final double AVOGADROS_NUMBER = 6.23156412e23;
          public static final double BOLTZMANN_CONSTANT = 1.12588456e-23;
      }
      
  • 结论

    接口只适用被用来定义类型,不应该被用来导出常量。

results matching ""

    No results matching ""